#ifndef __Renderer__h__included__
#define __Renderer__h__included__

#include <iostream>
#include <vector>
#include <map>

#include "neiderra/core/Base.h"
//#include "component.h"
#include "Object.h"
//#include "model.h"
#include "neiderra/gui/WindowImpl.h"
#include "neiderra/gui/Window.h"
#include "neiderra/math/Vectors.h"
// #include "Scene.h"
// #include "SceneObject.h"
#include "Texture.h"
#include "Alphabet.h"

using namespace neiderra::gui;
using namespace neiderra::core;
// using namespace neiderra::scene;
using namespace neiderra::math;

namespace neiderra {

	namespace rendering {

		class Transform;
		class Mesh;
		class Image;
		class Model;
		class Models;
		class TextString;
		class Sprite;

		class iRenderTarget;
		
		class PolyParticleSystem;
		class ParticleSystem;
		
		namespace sg { 
			class sgNode; 
			class sgDOFTranslateNode;
			class sgDOFRotateNode;
			class sgDOFScaleNode;
			class sgDOFNode;
			class sgStringNode;
			class sgParticleSystemNode;
		}
		
		using namespace sg;
		
		//! Rendering subsytem interface
		class iRenderer: public Base
		{
		public:
			class ERenderException{};
		public:
			iRenderer(Core* _core): Base(_core){ }
			virtual ~iRenderer(){}
		
			virtual void init(iRenderTarget*) =0;
		
			// Provides visualization
			virtual void update(double deltaT) =0;
		
			virtual void rotatef(float angle, vec3&) =0;
			virtual void rotatef(float angle, float x, float y, float z) =0;
			virtual void translatef(vec3&) =0;
			virtual void translatef(float x, float y, float z) =0;
			virtual void scalef(float x, float y, float z) =0;
			virtual void scalef(vec3&)=0;
		
			virtual void pushMatrix() =0;
			virtual void popMatrix() =0;
			virtual void multMatrix(float *m) =0;
		
			// Renders root node and it's children
			virtual void RenderRoot()=0;
			// Renders abstract object
			virtual void render(RenderingObject* obj) =0;
			// Renders 3d mesh
			virtual void render(Mesh* mesh, Texture* texture) =0;
			// Renders image
			virtual void render(Image* img, unsigned x, unsigned y) =0;
			// Renders text string
			virtual void render(TextString*, unsigned x, unsigned y) =0;
			// Renders whole scene
		// 	virtual void render(scene::aScene*) =0;
		
			virtual void render(Sprite*)=0;
		
			virtual void render(sg::sgNode*)=0;
			virtual void render(sg::sgDOFTranslateNode*)=0;
			virtual void render(sg::sgDOFRotateNode*)=0;
			virtual void render(sg::sgDOFScaleNode*)=0;
			virtual void render(sg::sgDOFNode*)=0;
			virtual void render(sg::sgStringNode*)=0;
			virtual void render(sg::sgParticleSystemNode*)=0;
		
		//	virtual void render(aSceneObject*)=0;
			
			virtual void render(vec3& v)=0;
			virtual void render(Alphabet*)=0;
			virtual void render(ParticleSystem*)=0;
			virtual void render(PolyParticleSystem*)=0;
			//virtual void render(sg::sgDOFOrientNode*)=0;
			virtual void identity()=0;
		
			virtual float getFPS()=0;
		
			// Set scenegraph root to the renderer
		// 	virtual void SetSceneRoot(sg::sgNode* node) {_root = node; }
			// Associate scene with renderer
		// 	virtual void SetScene(Scene* scene){_scene = scene; _root = scene->GetSceneRoot()->GetSGNode();}
		
			virtual void renderTexture(Texture* texture)=0;
		
			virtual void showAxes() =0;
			virtual void hideAxes() =0;
		
			virtual iRenderTarget* getTarget()=0;
		protected:
			iRenderTarget* target_;
			sg::sgNode* _root;
// 			scene::Scene* _scene;
			double _fps;
			double _timeElapsed;
		};
	}
}

#endif
